
import re
import parsedatetime as pdt
import parsedatetime_consts as pdc
from datetime import datetime
import time



class DateExtracterRE(object):
	dateExpressions = [
					# Matches numbered dates separated by either: [.-/] (month first or second)
					# Could be made more restrictive by including valid range for month and day, but the overall format should be restrictive enough
					# There will always be ambiguity about which is first, the month or the day. I believe day first is more common in US
					#("[0-9]{1,2}\/[0-9]{1,2}\/(19|20)([0-9]{2})", "%m/%d/%Y"),
					#("[0-9]{1,2}\.[0-9]{1,2}\(19|20)([0-9]{2})", "%m.%d.Y"),
					#("[0-9]{1,2}-[0-9]{1,2}-(19|20)([0-9]{2})", "%m-%d-Y"),
					("[0-9]{1,2}[\/ | - | \.][0-9]{1,2}[\/ | - | \.](19|20)([0-9]{2})", "%m/%d/%Y","%m.%d.Y", "%m-%d-Y"),

					# ISO Format YYYY-MM-DD
					("(19|20)([0-9]{2})-(0?[1-9]|1[012])-[0-9]{2}", "%Y-%m-%d"),
					
					# This one seems to work well, we need to add commas to it (also need to reverse order of month and day as another regex)
					# dd MMM yyyy ||
					# dd MMM, yyyy
					("((31(?!\ (Feb(\.)?(ruary)?|Apr(\.)?(il)?|June?|(Sep(?=\b|t)t?|Nov)(\.)?(ember)?)))|((30|29)(?!\ Feb(\.)?(ruary)?))|(29(?=\ Feb(ruary)?\ (((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)))))|(0?[1-9])|1\d|2[0-8])\ (Jan(\.)?(uary)?|Feb(\.)?(ruary)?|Ma(r(ch)?|y)|Apr(\.)?(il)?|Ju((ly?)|(ne?))|Aug(\.)?(ust)?|Oct(\.)?(ober)?|(Sep(?=\b|t)t?|Nov|Dec)(\.)?(ember)?),?\ ((1[6-9]|[2-9]\d)\d{2})",
					"%d %B %Y", "%d %b %Y", "%d %B, %Y", "%d %b, %Y", "%d %b. %Y", "%d %b., %Y"),

					# We need something like the one above MMM dd, yyyy
					
					# This one seems to work on cases where the month is second
					# (we may need to split it up into two to handle months first, and days first)
					# Fails on 01/02/2011
					# Subset of 1
					#"(0?[1-9]|[12][0-9]|3[01])[/.-](0?[1-9]|1[012])[/.-]((19|20)?\\d\\d)"

					
					# try to get Monthname dd, yyyy
					("(Jan(\.)?(uary)?|Feb(\.)?(ruary)?|Mar(\.)?(ch)?|Apr(\.)?(il)?|May|Jun(\.)?(e)?|Jul(\.)?(y)?|Aug(\.)?(ust)?|Sep(\.)?(tember)?|Oct(\.)?(ober)?|Nov(\.)?(ember)?|Dec(\.)?(ember)?)[ ]?[0-9]{1,2}(th)?(st)?[ ,]?[ ]?(19|20)([0-9]{2})", 
					"%B %d %Y", "%b %d %Y", "%B %d, %Y", "%b %d, %Y", "%b. %d, %Y", "%b. %d %Y", "%B %dth %Y", "%b %dth %Y", "%B %dst %Y", "%b %dst %Y"),
					
					# YYYY
					# This should be last. Other formats containing 'yyyy' contain more information 
					("(19|20)([0-9]{2})(\s|\.|$)", "%Y ", "%Y")
					
					]
	
	#
	# Adam was messing with these regular expressions!
	#
	# NOTES:
	#
	# (19|20)([0-9]{2})
	#	--> Matches a 4 digit year
	#
	# (0?[1-9]|[12][0-9]|3[01])[/.-](0?[1-9]|1[012])[/.-]((19|20)\\d\\d)
	# 	--> Matches numbered dates separated by either: [.-/]
	#	--> Month and day can be 1 or 2 digits, the year can be 2 or 4 digits
	#	(******This one may not be 100% correct, fails on input: 08/15/2011)
	#	(******This is because this regex expects the month second, perhaps make another like it for month first)
	#
	# -----------
	# - NEED:
	# -----------
	#
	# Regex that matches like the one above on named dates, but has the month first
	# (for example, January 12, 2009)
	#
	# Modify the regex above to allow for commas after the month
	# (for example, 12 January, 2010)
	#
	#
	
	compiledExp =[]
        
	def __init__(self):
		# Compile all of the date expressions
		for exp in self.dateExpressions:
			compiled = re.compile(exp[0], re.IGNORECASE)
			self.compiledExp.append((compiled, exp))
			
	def findDate(self,str):
		# For all compiled expressions
		date = None
		
		for exp in self.compiledExp:
			# compare expression to intput string
			dateStr = exp[0].search(str)
			if not dateStr is None:
				#convert date to dateTime object
				#print "Found date str: %s" % (dateStr.group())
				for i in range(1, len(exp[1])):
					try:
						#print "trying %s" %(exp[1][i])				
						date = datetime.strptime(dateStr.group(), exp[1][i])
						if not date is None:
							return date
					except:
						continue
		return date

	def removeDate(self, str):

		for exp in self.compiledExp:
			str = exp[0].sub(' ', str) 

		return str
			

    # returns datetime object if date/time is present in source datetimeString
    # else returns null
    # relative dates are adjusted to sourceTime
	def extractDates(self, strings, url, sourceTime=None):
		results = []        
		for str in strings:
			result = self.findDate(str)
			if result is not None:
				event = (result, str, url)
				results.append(event)     

		return results
	
		


######### MAIN ##################

#de = DateExtracterRE()

#sentence = raw_input("Enter String: ")

#result = de.findDate(sentence)
#print result

